<template>
	<view v-show="!data.hidden">
		<file-upload :modelValue="fileList" :max="max" :chooseNum="chooseNum" @chooseSuccess="chooseFile" @imgDelete="removeFile" ref="FileUploadRef"></file-upload>
	</view>
	<ksp-cropper
		v-if="data.fixedScale"
		style="left: 0; position: absolute;"
		mode="ratio"
		:width="data.fixedScale[0]"
		:height="data.fixedScale[1]"
		:url="cropperImg"
		@cancel="cropperCancel"
		@ok="cropperConfirm"
	></ksp-cropper>
</template>

<script setup lang="ts">
import { ref, reactive, watch, defineExpose } from 'vue'
import fileUpload from '@/components/common/file-upload/file-upload.vue'
import { uploadFile } from '@/service/common/upload'
import { getFileSuffix, toast } from '@/assets/js/utils'

const props = defineProps({
	//表单组件参数
	data: {
		type: Object,
		required: true
	},
	//双向绑定值
	modelValue: {}
})
const emit = defineEmits(['update:modelValue', 'valueChange'])
//单文件大小；单位兆（M）
const size = ref(props.data.size ? props.data.size : 5)
//回显可以显示的图片数
const max = ref(props.data.max ? props.data.max : 1)
//可选择的图片数（如果图片需要裁剪，默认只能选择一个图片）
const chooseNum = ref(props.data.fixedScale ? 1 : props.data.max)

//回显文件列表
const fileList = <any>ref([])

watch(props, (val: any) => {
	if (val.modelValue) {
		fileList.value = val.modelValue.split(',')
	} else {
		fileList.value = []
	}
})

//判断是否超出文件上传大小限制; 超出返回空字符串
const exceedsSize = (file: any) => {
	if (file.size <= size.value * 1024 * 1024) {
		let fileName = ''
		// #ifdef H5
		fileName = file.name
		// #endif
		// #ifdef MP-WEIXIN
		fileName = file.path
		// #endif
		return fileName
	} else {
		return ''
	}
}

//选择单个或多个文件
const chooseFile = async (files: any) => {
	let uploadFile = []
	//剔除上传队列中超过文件大小限制的文件
	files.tempFiles.map((item: any, index: number) => {
		let fileName = exceedsSize(item)
		if (fileName != '') {
			uploadFile.push({
				filePath: files.tempFilePaths[index],
				fileName: fileName
			})
		}
	})
	//判断是否需要裁剪
	if (props.data.fixedScale) {
		if (uploadFile.length == 0) {
			toast(`选择的文件超过 ${size.value}MB上传大小限制!`)
			return
		}
		cropperImg.value = files.tempFilePaths[0]
		// #ifdef H5
		cropperImgSuffix.value = getFileSuffix(files.tempFiles[0].name)
		// #endif
		// #ifdef MP-WEIXIN
		cropperImgSuffix.value = getFileSuffix(files.tempFiles[0].path)
		// #endif
		return
	}
	uni.showLoading({
		title: '上传中'
	})
	let uploadedFile = []
	//异步进行队列中的文件
	await Promise.all(
		uploadFile.map(async (item: any, index: number) => {
			let suffix = getFileSuffix(item.fileName)
			let fileUrl = await upload(item.filePath, suffix)
			uploadedFile[index] = fileUrl
		})
	)
	//判断是否有满足上传条件的文件
	if (uploadedFile.length > 0) {
		fileList.value.push(uploadedFile)
		valueChange()
	}
	uni.hideLoading()
	//提示上传队列中有几个不满足上传条件的文件
	uploadFile.length < files.tempFiles.length ? toast(`上传队列中【${files.tempFiles.length - uploadFile.length}】个文件超过 ${size.value}MB上传大小限制!`) : ''
}

//裁剪图片地址
const cropperImg = ref('')
//裁剪图片后缀名
const cropperImgSuffix = ref('')
//确定裁剪图片
const cropperConfirm = async (file: any) => {
	//解决裁剪组件回调完成延迟关闭全局loading的问题
	await (<any>setTimeout(() => {}, 200))
	let suffix = cropperImgSuffix.value
	cropperCancel()
	uni.showLoading({
		title: '上传中'
	})
	let fileUrl = await upload(file.path, suffix)
	uni.hideLoading()
	fileList.value.push(fileUrl)
	valueChange()
}

//取消裁剪图片
const cropperCancel = () => {
	cropperImg.value = ''
	cropperImgSuffix.value = ''
}

//删除单个文件
const removeFile = (e: any) => {
	valueChange()
}

//上传文件发生改变,改变双向绑定值
const valueChange = () => {
	emit('update:modelValue', fileList.value.join(','))
	//单例模式返回最新上传的图片
	if (max.value == 1) {
		let imgUrl = fileList.value[fileList.value.length - 1]
		Array.isArray(imgUrl) ? (imgUrl = imgUrl[imgUrl.length - 1]) : ''
		emit('valueChange', fileList.value[fileList.value.length - 1])
	} else {
		emit('valueChange', fileList.value.join(','))
	}
}

//上传图片
const upload = async (fileUri: any, suffix: string) => {
	let [result, err] = await uploadFile({
		fileUri: fileUri,
		fileSuffix: suffix,
		filePath: props.data.fileType,
		watermarkType: props.data.watermarkType,
		uploadProgress: (progress: number) => {}
	})
	if (result) {
		return result
	} else {
	}
}

//主动触发选择文件
const FileUploadRef = ref()
const selectFile = () => {
	FileUploadRef.value.selectFile()
}
//子组件向父组件暴露函数调用
defineExpose({ selectFile })
</script>

<style></style>
